﻿namespace Webinator.Util
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;

    /// <summary>
    /// Contains various file and folder functions.
    /// </summary>
    internal class FileUtil
    {
        /// <summary>
        /// Recursively searchs the application folder for a file that looks like the value passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>
        /// The file found that is like the value provided.
        /// </returns>
        internal string GetPathOfFileLike(string value)
        {
            var files = GetFilesRecursive(AppDomain.CurrentDomain.BaseDirectory);
            return (from file in files let name = Path.GetFileNameWithoutExtension(file) where name != null && name.ToLower().Contains(value) select file).FirstOrDefault();
        }

        /// <summary>
        /// Recursively searchs the application folder for a file that looks like the value passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>
        /// The file found that is like the value provided.
        /// </returns>
        internal IEnumerable<string> GetPathOfFilesLike(string value)
        {
            var files = GetFilesRecursive(AppDomain.CurrentDomain.BaseDirectory);

            return (from file in files let name = Path.GetFileName(file) where name != null && name.ToLower().Contains(value) select file).ToList();
        }

        /// <summary>
        /// Recursively finds all files in the directory provided.
        /// </summary>
        /// <param name="directory">The directory.</param>
        /// <returns>
        /// All files found in the directory and its subfolders.
        /// </returns>
        internal IEnumerable<string> GetFilesRecursive(string directory)
        {
            // 1.
            // Store results in the file results list.
            var result = new List<string>();

            // 2.
            // Store a stack of our directories.
            var stack = new Stack<string>();

            // 3.
            // Add initial directory.
            stack.Push(directory);

            // 4.
            // Continue while there are directories to process
            while (stack.Count > 0)
            {
                // A.
                // Get top directory
                var dir = stack.Pop();

                try
                {
                    // B
                    // Add all files at this directory to the result List.
                    result.AddRange(Directory.GetFiles(dir, "*.*"));

                    // C
                    // Add all directories at this directory.
                    foreach (string dn in Directory.GetDirectories(dir))
                    {
                        stack.Push(dn);
                    }
                }
                catch
                {
                    // D
                    // Could not open the directory
                }
            }

            return result;
        }
    }
}
